#ifndef GU_PROTOCOL_H
#define GU_PROTOCOL_H

#include <stdint.h>
#include <stdbool.h>
#include <sys/socket.h>
#include <netinet/in.h>

// GuDB Protocol Version
#define GU_PROTOCOL_VERSION     1
#define GU_DEFAULT_PORT         7777
#define GU_MAX_PACKET_SIZE      (1 * 1024 * 1024)  // 1MB
#define GU_HEADER_SIZE          8
#define GU_MAX_USERNAME_SIZE    64
#define GU_MAX_PASSWORD_SIZE    128
#define GU_MAX_DATABASE_SIZE    64

// GuDB Command Types
typedef enum {
    GU_CMD_CONNECT      = 0x01,
    GU_CMD_AUTH         = 0x02,
    GU_CMD_EXEC         = 0x03,
    GU_CMD_QUERY        = 0x04,
    GU_CMD_QUIT         = 0x05,
    GU_CMD_PING         = 0x06,
    GU_CMD_HELP         = 0x07
} gu_command_t;

// GuDB Response Types
typedef enum {
    GU_RESP_OK          = 0x00,
    GU_RESP_ERROR       = 0x01,
    GU_RESP_RESULT      = 0x02,
    GU_RESP_AUTH_OK     = 0x03,
    GU_RESP_AUTH_FAIL   = 0x04,
    GU_RESP_PONG        = 0x05
} gu_response_t;

// GuDB Status Codes
typedef enum {
    GU_STATUS_OK        = 0,
    GU_STATUS_ERROR     = 1,
    GU_STATUS_AUTH_FAIL = 2,
    GU_STATUS_SYNTAX    = 3,
    GU_STATUS_NO_TABLE  = 4,
    GU_STATUS_NO_DB     = 5
} gu_status_t;

// GuDB Packet Header (8 bytes)
typedef struct {
    uint32_t length;        // Payload length (4 bytes)
    uint8_t command;        // Command type (1 byte)
    uint8_t status;         // Status code (1 byte)  
    uint16_t flags;         // Flags (2 bytes)
} __attribute__((packed)) gu_header_t;

// GuDB Packet
typedef struct {
    gu_header_t header;
    uint8_t* payload;
    size_t payload_size;
} gu_packet_t;

// Connection Info
typedef struct {
    char username[GU_MAX_USERNAME_SIZE];
    char password[GU_MAX_PASSWORD_SIZE];
    char database[GU_MAX_DATABASE_SIZE];
} gu_connection_t;

// Query Result
typedef struct {
    uint32_t column_count;
    char** column_names;
    uint32_t row_count;
    char*** rows;
    uint64_t* row_lengths;
} gu_result_t;

// Client Connection
typedef struct {
    int sockfd;
    struct sockaddr_in server_addr;
    bool connected;
    bool authenticated;
    gu_connection_t conn_info;
} gu_client_t;

// Protocol Functions

// Packet Management  
gu_packet_t* gu_packet_create(uint8_t cmd_or_resp, uint32_t payload_size);
void gu_packet_destroy(gu_packet_t* packet);
int gu_packet_send(int sockfd, gu_packet_t* packet);
gu_packet_t* gu_packet_recv(int sockfd);

// Message Construction
gu_packet_t* gu_create_connect_packet(const char* username, const char* password, const char* database);
gu_packet_t* gu_create_exec_packet(const char* sql);
gu_packet_t* gu_create_query_packet(const char* sql);
gu_packet_t* gu_create_quit_packet(void);
gu_packet_t* gu_create_ping_packet(void);

// Response Handling
int gu_parse_response(gu_packet_t* packet, gu_result_t** result);
gu_result_t* gu_parse_result_payload(const char* payload, uint32_t length);
const char* gu_get_status_message(gu_status_t status);
const char* gu_get_command_name(gu_command_t cmd);

// Result Management
gu_result_t* gu_result_create(uint32_t column_count);
void gu_result_destroy(gu_result_t* result);
int gu_result_add_column(gu_result_t* result, uint32_t index, const char* name);
int gu_result_add_row(gu_result_t* result, char** row_data);

// Utility Functions
void gu_write_uint32(uint8_t* buffer, uint32_t value);
void gu_write_uint16(uint8_t* buffer, uint16_t value);
uint32_t gu_read_uint32(const uint8_t* buffer);
uint16_t gu_read_uint16(const uint8_t* buffer);
size_t gu_write_string(uint8_t* buffer, const char* str);
char* gu_read_string(const uint8_t* buffer, size_t max_len);

#endif // GU_PROTOCOL_H